package cn.baage.campus.scheduled;

import cn.baage.campus.constant.CacheConstant;
import cn.baage.campus.model.vo.PostingQueryReqVO;
import cn.baage.campus.model.vo.PostingResVO;
import cn.baage.campus.service.PostingService;
import cn.baage.campus.service.RedisService;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @Description: 定时任务
 * @Author: 八阿哥
 * @url: baage.cn
 * @Version: 1.0
 **/
@Component
@Configurable
@EnableScheduling
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Slf4j
public class ScheduledTasks {

    private final RedisService<Integer> redisService;
    private final PostingService postingService;

    /**
     * 每 2 小时更新点赞数
     * CORS: 0 0 0/2 * * ?
     *
     */
    @Scheduled(cron = "0 0 0/2 * * ?")
    public void updatePosingLikeNum() {
        log.info("更新【点赞数】任务开始");
        String cacheKey = CacheConstant.LIKE_NUM_KEY + "1:*";
        Set<String> keys = redisService.getKeys(cacheKey);
        for (String key : keys) {
            Integer readNum = redisService.get(key);
            String[] split = key.split(":");
            try {
                postingService.updateLikeNum(split[split.length - 1], readNum);
                redisService.delete(key);
            } catch (Exception e) {
                log.info("更新【点赞数】任务失败，key: {}", key);
            }
        }
        log.info("更新【点赞数】结束");
    }


    /**
     * 每天 2 点更新阅读数
     * CORS：0 0 2 * * ?
     *
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void updatePostingReadingNum() {
        log.info("更新【阅读数】任务开始");
        String cacheKey = CacheConstant.READING_NUM_KEY + "*";
        Set<String> keys = redisService.getKeys(cacheKey);
        for (String key : keys) {
            Integer readNum = redisService.get(key);
            String[] split = key.split(":");
            try {
                postingService.updatePostingReadNum(split[split.length - 1], readNum);
                redisService.delete(key);
            } catch (Exception e) {
                log.info("更新【阅读数】失败，key: {}", key);
            }
        }
        log.info("更新【阅读数】任务结束");
    }


    /**
     * 每天 0 点 30 分 更新热度分数。注：只刷新近 3 天的热度分数
     * CORS：0 30 0 * * ?
     *
     */
    @Scheduled(cron = "0 30 0 * * ?")
    public void updatePostingHotScore() {
        log.info("更新【热度分数】任务开始");
        Date now = new Date();
        // 获取近 3 天的帖子
        PostingQueryReqVO postingQuery = new PostingQueryReqVO();
        Date startDate = Date.from(LocalDateTime.now().minusDays(3).atZone(ZoneId.systemDefault()).toInstant());
        postingQuery.setStartDate(startDate);
        List<PostingResVO> postingList = postingService.listPosting(postingQuery);
        for (PostingResVO postingResVO : postingList) {
            // 获取时间差 天数
            long diffInMilliseconds = now.getTime() - postingResVO.getCreateTime().getTime();
            int diffInHours = (int) TimeUnit.MILLISECONDS.toHours(diffInMilliseconds);
            double hotScore = postingResVO.getReadNum() * 0.2 +
                    postingResVO.getCommentCount() * 0.4 +
                    postingResVO.getLikeNum() * 0.3 +
                    (72 - diffInHours) * 0.1;
            try {
                postingService.updateHotScore(postingResVO.getId(), Math.max(0, hotScore));
            } catch (Exception e) {
                log.error("更新帖子热点分数失败，帖子ID：{}", postingResVO.getId());
            }
        }
        // 缓存热点帖子
        List<PostingResVO> hotPosting = postingService.listHotPosting();
        hotPosting.forEach(p -> {
            p.setAbstractContent(p.getAbstractContent().replace("<br>", ""));
        });
        String hostPostingJson = JSON.toJSONString(hotPosting);
        redisService.setJsonVal(CacheConstant.HOT_POSTING_KEY, hostPostingJson);
        log.info("更新【热度分数】任务结束");
    }






}